package user.zc.action.comp;



import javax.swing.*;
import java.awt.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;

public abstract class SaveOrUpdateAction<T,R>  extends Action<R> {

    protected static final Integer SCALE = 40;
    public enum InputType{
        Input("input"),MediumInput("input",40),ContentType("textarea",new Integer[]{10,40}),ColumnType("select",new String[]{"char","varchar","int","tinyint","bigint","float","double","decimal","date","time","datetime","timestamp","enum","text","json"}),
        BooleanType("select",new String[]{"false","true"});
        private String[] select;
        private Integer[] rc;
        private String type;
        private Integer columns;
        InputType(String type,String[] select){
            this.type = type;
            this.select = select;
        }
        InputType(String type,Integer[] rc){
            this.type = type;
            this.rc = rc;
        }
        InputType(String type,Integer columns){
            this.type = type;
            this.columns = columns;
        }
        InputType(String type){
            this.type = type;
            this.columns = 30;
        }
    }


    private java.util.List<IField> requiredList = new ArrayList<IField>();
    private java.util.List<IField> fields = new ArrayList<IField>();
    private JScrollPane scrollPane = null;
    private JPanel panel = null;
    private T dto;
    private Integer width;
    private Integer height;
    public SaveOrUpdateAction(Consumer<R> callback,T dto,Integer width,Integer height) {
        super(callback);
        this.width = width;
        this.height = height;
        this.dto = dto;
        panel = new JPanel(new FlowLayout(FlowLayout.LEFT)) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(width, height);
            }
        };
        scrollPane = new JScrollPane(panel);
    }


    protected void addItem(String label,String name,boolean required,InputType inputType,String defaultText)throws Exception{
        JPanel line = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JLabel jlabel = new JLabel(label+"：");
        line.add(jlabel);
        IField field = null;
        if(inputType.type.equals("select")){
            field = new IComboBox(inputType.select,label,width-78,name,ifnull((dto!=null?getValueByName(dto,name):null),defaultText,""));
            line.add((IComboBox)field);
        }else if(inputType.type.equals("textarea")){
                field = new ITextArea(label,name,ifnull((dto!=null?getValueByName(dto,name):null),defaultText,""),inputType.rc[0],inputType.rc[1]);
                ScrollPane scrollPane = new ScrollPane();
                scrollPane.setPreferredSize(new Dimension(width-78,600));
                scrollPane.add((ITextArea)field);
                line.add(scrollPane);
        }else{
            field = new ITextField(label,name,ifnull((dto!=null?getValueByName(dto,name):null),defaultText,""),inputType.columns);
            line.add((ITextField)field);
        }
        if(required){
            requiredList.add(field);
        }
        panel.add(line);
        fields.add(field);
    }

    protected void addItem(String label,String name,boolean required,String defaultText)throws Exception{
        addItem(label,name,required,InputType.Input,defaultText);
    }

    protected void addItem(String label,String name,boolean required,InputType inputType)throws Exception{
        addItem(label,name,required,inputType,null);
    }
    protected void addItem(String label,String name,boolean required)throws Exception{
        addItem(label,name,required,InputType.Input,null);
    }
    private String getValueByName(T dto,String feildName)throws Exception{

        for(Class cla  = dto.getClass();!cla.equals(Object.class);cla=cla.getSuperclass()){
            try {
                Field declaredField = cla.getDeclaredField(feildName);
                declaredField.setAccessible(true);
                return Optional.ofNullable( declaredField.get(dto)).orElse("").toString();
            } catch (Exception e) {
            }
        }

//        throw new Exception("列【"+feildName+"】在Class【"+dto.getClass().getSimpleName()+"】中不存在");
        return null;
    }

    private boolean checkRequired(){
        return checkRequired(requiredList.toArray(new IField[]{}));
    }

    protected void openDialog(String title,Consumer<T> saveHandler)throws Exception{

        ActionDialog dialog = new ActionDialog(null, title,scrollPane,()->{
            if(checkRequired()){
                try {
                    T saveDto = map2Entity(mapping());
                    saveHandler.accept(saveDto);
                    return true;
                } catch (Exception e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(null,
                            e.getMessage(), "操作失败", JOptionPane.ERROR_MESSAGE);
                }
            }
            return false;
        });
        dialog.setVisible(true);
    }

   /* protected T collect(Class<T> clazz)throws Exception{
        T instance = clazz.newInstance();
        for (ITextField field : fields) {
            for (Class clz = clazz;!clz.equals(Object.class);clz = clz.getSuperclass()){
                try {
                    Field targetField = clz.getDeclaredField(field.getName());
                    targetField.setAccessible(true);
                    targetField.set(instance,field.getText());
                    break;
                } catch (NoSuchFieldException e) {

                } catch (SecurityException e) {
                    e.printStackTrace();
                }
            }
        }
        return instance;
    }*/

    protected abstract T map2Entity(Map<String,String> map);

    protected Map<String,String> mapping(){
        Map<String,String> map = new HashMap<>();
        for (IField field : fields) {
            map.put(field.getName(),ifnull(field.getText(),field.getDefaultValue(),""));
        }
        return map;
    }

    private String ifnull(String value,String defaultValue,String finalValue){
        if((defaultValue!=null || finalValue!=null) && (null==value||"".equals(value))){
            return ifnull(defaultValue,finalValue,null);
        }
        return value;
    }
}
